package ogdkp;

import java.util.List;

import ogdkp.actions.AddLootAction;
import ogdkp.actions.AddLootActionInfo;
import ogdkp.actions.EditLootAction;
import ogdkp.actions.RemoveLootAction;
import ogdkp.om.ITreeNode;
import ogdkp.om.Loot;
import ogdkp.om.LootCache;
import ogdkp.om.Player;
import ogdkp.providers.DKPComparator;
import ogdkp.providers.DKPContentProvider;
import ogdkp.providers.DKPFilter;
import ogdkp.providers.DKPLabelProvider;
import ogdkp.utils.DKPUtils;

import org.eclipse.core.commands.ExecutionException;
import org.eclipse.core.commands.NotEnabledException;
import org.eclipse.core.commands.NotHandledException;
import org.eclipse.core.commands.common.NotDefinedException;
import org.eclipse.jface.action.IMenuListener;
import org.eclipse.jface.action.IMenuManager;
import org.eclipse.jface.action.MenuManager;
import org.eclipse.jface.dialogs.MessageDialog;
import org.eclipse.jface.layout.TreeColumnLayout;
import org.eclipse.jface.viewers.ColumnWeightData;
import org.eclipse.jface.viewers.DoubleClickEvent;
import org.eclipse.jface.viewers.IDoubleClickListener;
import org.eclipse.jface.viewers.IStructuredSelection;
import org.eclipse.jface.viewers.TreeViewer;
import org.eclipse.jface.viewers.TreeViewerColumn;
import org.eclipse.swt.SWT;
import org.eclipse.swt.events.SelectionAdapter;
import org.eclipse.swt.events.SelectionEvent;
import org.eclipse.swt.events.SelectionListener;
import org.eclipse.swt.layout.GridData;
import org.eclipse.swt.layout.GridLayout;
import org.eclipse.swt.widgets.Button;
import org.eclipse.swt.widgets.Combo;
import org.eclipse.swt.widgets.Composite;
import org.eclipse.swt.widgets.Label;
import org.eclipse.swt.widgets.Menu;
import org.eclipse.swt.widgets.Tree;
import org.eclipse.swt.widgets.TreeColumn;
import org.eclipse.ui.IWorkbenchPartSite;
import org.eclipse.ui.handlers.IHandlerService;
import org.eclipse.ui.part.ViewPart;

public class View extends ViewPart {
	public static final String ID = "OGDKP.view";

	private TreeViewer viewer;

	private DKPComparator comparator;

	private List<Player> players;

	private Combo modeCombo;

	private Combo bossCombo;

	private Combo instanceCombo;

	@Override
	public void createPartControl(final Composite parent) {
		final Composite client = new Composite(parent, SWT.NONE);
		final GridLayout layout = new GridLayout();
		layout.numColumns = 2;
		client.setLayout(layout);
		client.setLayoutData(new GridData(GridData.FILL, GridData.FILL, true, true));
		final Composite tableComposite = new Composite(client, SWT.NONE);
		tableComposite.setLayoutData(new GridData(GridData.FILL, GridData.FILL, true, true));
		createTable(tableComposite);
		createSideComposite(client);
	}

	private void createSideComposite(final Composite parent) {
		final Composite client = new Composite(parent, SWT.NONE);
		final GridLayout layout = new GridLayout();
		client.setLayout(layout);
		final GridData clientData = new GridData();
		clientData.widthHint = 120;
		clientData.verticalAlignment = GridData.BEGINNING;
		client.setLayoutData(clientData);

		new Label(client, SWT.NONE).setText("Instance:");
		instanceCombo = new Combo(client, SWT.NONE);
		for (final String raid : LootCache.getInstance().getLocations()) {
			instanceCombo.add(raid);
		}
		instanceCombo.setLayoutData(new GridData(GridData.FILL_HORIZONTAL));
		instanceCombo.addSelectionListener(new SelectionAdapter() {
			@Override
			public void widgetSelected(final SelectionEvent e) {
				if (bossCombo != null) {
					bossCombo.removeAll();
					for (final String boss : LootCache.getInstance().getBosses(instanceCombo.getText())) {
						bossCombo.add(boss);
					}
				}
			}
		});
		instanceCombo.select(0);

		new Label(client, SWT.NONE).setText("Difficulty:");
		modeCombo = new Combo(client, SWT.NONE);
		modeCombo.add("Normal");
		modeCombo.add("Heroic");
		modeCombo.setLayoutData(new GridData(GridData.FILL_HORIZONTAL));
		modeCombo.select(0);

		new Label(client, SWT.NONE).setText("Boss:");
		bossCombo = new Combo(client, SWT.NONE);
		for (final String boss : LootCache.getInstance().getBosses(instanceCombo.getText())) {
			bossCombo.add(boss);
		}
		bossCombo.setLayoutData(new GridData(GridData.FILL_HORIZONTAL));

		final Button costsBtn = new Button(client, SWT.PUSH);
		costsBtn.setText("View Costs");
		costsBtn.addSelectionListener(new SelectionAdapter() {
			@Override
			public void widgetSelected(final SelectionEvent e) {
				MessageDialog.openInformation(costsBtn.getShell(), "DKP Costs",
				        "\t* Category 1:  10 DKP  Thrown/Offhand\n"
				                + "\t* Category 2:  15 DKP  Neck/Back/Wrist/Rings\n"
				                + "\t* Category 3:  20 DKP  Shoulder/Hands/Waist/Feet\n"
				                + "\t* Category 4:  25 DKP  Head/Chest/Pants/Trinkets\n"
				                + "\t* Category 5:  35 DKP  1H Weapons/Firestones\n"
				                + "\t* Category 6:  40 DKP  2H Weapons\n");
			}
		});
		costsBtn.setLayoutData(new GridData(GridData.FILL_HORIZONTAL));

		final Button setRaidersBtn = new Button(client, SWT.PUSH);
		setRaidersBtn.setText("Set Raiders");
		setRaidersBtn.addSelectionListener(new SelectionAdapter() {
			@Override
			public void widgetSelected(final SelectionEvent e) {
				executeCommand("OGDKP.setRaiders.command", getSite());
			}
		});
		setRaidersBtn.setLayoutData(new GridData(GridData.FILL_HORIZONTAL));

		final Button exportBtn = new Button(client, SWT.PUSH);
		exportBtn.setText("Export");
		exportBtn.addSelectionListener(new SelectionAdapter() {
			@Override
			public void widgetSelected(final SelectionEvent e) {
				executeCommand("OGDKP.export.command", getSite());
			}
		});
		exportBtn.setLayoutData(new GridData(GridData.FILL_HORIZONTAL));

	}

	private static void executeCommand(final String id, final IWorkbenchPartSite site) {
		final IHandlerService handlerService = (IHandlerService) site.getService(IHandlerService.class);
		try {
			handlerService.executeCommand(id, null);
		} catch (final ExecutionException e1) {
			// TODO Auto-generated catch block
			e1.printStackTrace();
		} catch (final NotDefinedException e1) {
			// TODO Auto-generated catch block
			e1.printStackTrace();
		} catch (final NotEnabledException e1) {
			// TODO Auto-generated catch block
			e1.printStackTrace();
		} catch (final NotHandledException e1) {
			// TODO Auto-generated catch block
			e1.printStackTrace();
		}

	}

	private void createTable(final Composite parent) {
		viewer = new TreeViewer(parent, SWT.FULL_SELECTION | SWT.MULTI | SWT.H_SCROLL | SWT.V_SCROLL);
		comparator = new DKPComparator();
		viewer.setComparator(comparator);
		viewer.addFilter(new DKPFilter());
		createColumns();
		viewer.setContentProvider(new DKPContentProvider());
		viewer.setLabelProvider(new DKPLabelProvider());

		createContextMenu(viewer);

		players = DKPUtils.buildPlayerList();
		viewer.setInput(players.toArray());
		viewer.getTree().setHeaderVisible(true);
		viewer.getTree().setLinesVisible(true);
		viewer.addDoubleClickListener(new IDoubleClickListener() {

			@Override
			public void doubleClick(final DoubleClickEvent event) {
				final IStructuredSelection selection = (IStructuredSelection) event.getSelection();
				final ITreeNode firstNode = ((ITreeNode) selection.getFirstElement());
				if (firstNode instanceof Player) {
					new AddLootAction((Player) firstNode, viewer, new AddLootActionInfo(modeCombo.getText(), bossCombo
					        .getText(), instanceCombo.getText())).run();
				} else if (firstNode instanceof Loot) {
					new EditLootAction((Loot) firstNode, viewer).run();
				}

			}

		});

		final Tree tree = viewer.getTree();
		comparator.setColumn(4);
		tree.setSortDirection(comparator.getDirection());
		tree.setSortColumn(tree.getColumn(4));
		viewer.refresh();

	}

	private void createContextMenu(final TreeViewer tree) {
		final MenuManager mgr = new MenuManager("#PopupMenu", "contextMenu.player.table");
		mgr.setRemoveAllWhenShown(true);
		final Menu menu = mgr.createContextMenu(tree.getControl());
		mgr.addMenuListener(new IMenuListener() {

			@Override
			public void menuAboutToShow(final IMenuManager manager) {
				updateContextMenu(mgr);

			}

		});
		tree.getTree().setMenu(menu);

	}

	protected void updateContextMenu(final MenuManager mgr) {
		final IStructuredSelection selection = (IStructuredSelection) viewer.getSelection();
		final ITreeNode firstNode = ((ITreeNode) selection.getFirstElement());
		if (firstNode instanceof Player) {
			mgr.add(new AddLootAction((Player) firstNode, viewer, new AddLootActionInfo(modeCombo.getText(), bossCombo
			        .getText(), instanceCombo.getText())));
		} else if (firstNode instanceof Loot) {
			mgr.add(new EditLootAction((Loot) firstNode, viewer));
			mgr.add(new RemoveLootAction((Loot) firstNode, viewer));
		}

	}

	private void createColumns() {
		final String[] headers = { "Name", "Class", "Initial", "Spent", "Current" };
		final int[] weight = { 40, 15, 15, 15, 15 };
		final TreeColumnLayout layout = new TreeColumnLayout();
		viewer.getTree().getParent().setLayout(layout);
		for (int i = 0; i < headers.length; i++) {
			final TreeViewerColumn viewerColumn = new TreeViewerColumn(viewer, SWT.NONE);
			final TreeColumn column = viewerColumn.getColumn();
			column.setText(headers[i]);
			layout.setColumnData(column, new ColumnWeightData(weight[i]));
			column.setResizable(true);
			column.setMoveable(true);
			column.addSelectionListener(getSelectionAdapter(column, i));
		}

	}

	private SelectionListener getSelectionAdapter(final TreeColumn column, final int index) {
		final SelectionAdapter adapter = new SelectionAdapter() {
			@Override
			public void widgetSelected(final SelectionEvent e) {
				comparator.setColumn(index);
				final int dir = comparator.getDirection();
				viewer.getTree().setSortDirection(dir);
				viewer.getTree().setSortColumn(column);
				viewer.refresh();
			}
		};
		return adapter;
	}

	/**
	 * Passing the focus request to the viewer's control.
	 */
	@Override
	public void setFocus() {
		viewer.getControl().setFocus();
	}

	public List<Player> getModel() {
		return players;
	}

	public String getSelectedInstance() {
		return instanceCombo.getText();
	}

	public void refresh() {
		viewer.refresh();

	}
}